package cs301.msflags;

import java.io.Serializable;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

/**
 * @author John Olennikov
 * @author Kyanne Mayfield
 * @author Allie Seibert
 * @author Emilia Holbik
 * @version 12/7/2012
 * 
 *          This class contains information to draw each of the individual
 *          spaces which make up the entire board.
 * 
 *          This class draws one space on the board and determines the
 *          attributes of the space such as whether the space is covered or
 *          uncovered, if the space has a flag, etc.
 */

public class BoardSpace implements Serializable {

	/**
	 * Unique ID for Serializable classes
	 */
	private static final long serialVersionUID = -6612187510657690078L;
	
	/**
	 * Variables to describe the spaceStatus variable
	 */
	
	private static int UNCOVERED = 0;
	private static int COVERED = 1;
	private static int BLUE_FLAG = 2;
	private static int RED_FLAG = 3;
	private static int EMPTY = 0;
	private static int MINE = 9;

	/**
	 * Colors with which to set the numbers in the BoardSpaces next to mines
	 */
	
	private static int[] colors = { Color.WHITE, Color.BLUE, Color.GREEN,
			Color.RED, Color.rgb(49, 0, 98), Color.rgb(24, 167, 181),
			Color.rgb(112, 28, 28), Color.rgb(9, 22, 87),
			Color.rgb(138, 51, 36), Color.BLACK };

	/**
	 * The length and width of our board space, which is a square
	 */

	public static int SPACE_SIZE = 38;

	/**
	 * Contains a value 0-9, where 0: no mines are in the surrounding square 1:
	 * one mine is in the surrounding square, etc. 9: this space contains a mine
	 */

	private int spaceValue = 0;

	/**
	 * Contains the values 0-3 based on whether the space is UNCOVERED, COVERED,
	 * has a BLUE_FLAG, or has a RED_FLAG.
	 */

	private int spaceStatus = 1;

	/**
	 * Contains the x-position of the top left corner of where this space will
	 * be drawn
	 */

	private int startX = 0;

	/**
	 * Contains the y-position of the top left corner of where this space will
	 * be drawn
	 */

	private int startY = 0;

	/**
	 * Constructor creates a BoardSpace 
	 * 
	 * @param initStartX  top left x-coordinate (in pixels) for drawing this
	 *        BoardSpace
	 * @param initStartY  top left y-coordinate (in pixels) for drawing this
	 *        BoardSpace
	 */
	public BoardSpace(int initStartX, int initStartY) {
		this.startX = initStartX;
		this.startY = initStartY;
	}

	/**
	 * @return true if this space has not been uncovered,
	 * 			false, otherwise.
	 */
	public boolean isCovered() {
		return spaceStatus > UNCOVERED;
	}

	/**
	 * @return true if this space is flagged,
	 * 			false, otherwise.
	 */
	public boolean isFlagged() {
		return spaceStatus > COVERED;

	}
	
	/**
	 * @return true if this space has a blue flag,
	 * 			false, otherwise.
	 */
	public boolean isBlueFlagged()
	{
		return spaceStatus == BLUE_FLAG;
	}
	
	/**
	 * @return true if this space has a red flag,
	 * 			false, otherwise.
	 */
	public boolean isRedFlagged()
	{
		return spaceStatus == RED_FLAG;
	}

	/**
	 * Handles flag action for blue player.
	 * 
	 * @param hasFlag  whether or not the player has flags available to place
	 * @return the number by which the player's amount of available flags 
	 * 			should be increased.
	 */
	public int flagBlue(boolean hasFlag) {
		// Place a flag if the space is covered and not already flagged,
		// and the player has flags available to place.
		if (spaceStatus == COVERED && hasFlag) {
			spaceStatus = BLUE_FLAG;
			return -1;
		// If the space already has a blue flag, remove it.
		} else if (spaceStatus == BLUE_FLAG) {
			spaceStatus = COVERED;
			return 1;
		// Otherwise, a flag cannot be placed.
		} else {
			return 0;
		}
	}
	
	/**
	 * Handles flag action for red player.
	 * 
	 * @param hasFlag  whether or not the player has flags available to place
	 * @return the number by which the player's amount of available flags 
	 * 			should be increased.
	 */
	public int flagRed(boolean hasFlag) {
		// Same as flagBlue method, except for the red player.
		if (spaceStatus == COVERED && hasFlag) {
			spaceStatus = RED_FLAG;
			return -1;
		} else if (spaceStatus == RED_FLAG) {
			spaceStatus = COVERED;
			return 1;
		} else {
			return 0;
		}
	}

	/**
	 * @return whether or not this space has a mine
	 */
	public boolean hasMine() {
		return spaceValue == MINE;
	}

	/**
	 * @return the number that this space contains (0 if empty and 9 if
	 *         mine)
	 */
	public int getSpaceValue() {
		return this.spaceValue;
	}

	/**
	 * Sets the value of this space:
	 * 0 - 8: this number of mines are contained in surrounding space  
	 * 9: this space contains a mine
	 * 
	 * @param newSpaceValue  new space value
	 */

	public void setSpaceValue(int newSpaceValue) {
		this.spaceValue = newSpaceValue;
	}

	/**
	 * @return the spaceStatus (whether uncovered, flagged, or covered)
	 */
	public int getSpaceStatus() {
		return this.spaceStatus;
	}

	/**
	 * @param newSpaceStatus  new spaceStatus (changed when user flags or 
	 *        uncovers)
	 */
	public void setSpaceStatus(int newSpaceStatus) {
		this.spaceStatus = newSpaceStatus;
	}

	/**
	 * Increments spaceValue instance variable to reflect the value of this
	 * BoardSpace.
	 */
	public void countNeighboringMine() {
		if (!hasMine()) {
			spaceValue++;
		}
	}

	/**
	 * Draws this BoardSpace on the SurfaceView
	 * 
	 * @param canvas  on which to draw
	 */
	public void draw(Canvas canvas) {
		//whether or not we should draw the "uncovered" version of this 
		//BoardSpace
		boolean drawEmblem = false;
		
		Paint myPaint = new Paint();
		
		//draw generically covered spaces when drawEmblem is false
		if (spaceStatus == COVERED) {
			myPaint.setColor(Color.GRAY);
		} else if (spaceStatus == RED_FLAG) {
			myPaint.setColor(Color.RED);
		} else if (spaceStatus == BLUE_FLAG) {
			myPaint.setColor(Color.BLUE);
		} else {
			//we know that the space has been uncovered
			drawEmblem = true;
			myPaint.setColor(Color.WHITE);
		}
		//draw the BoardSpace's square with the selected color
		canvas.drawRect(startX, startY, startX + SPACE_SIZE, startY
				+ SPACE_SIZE, myPaint);
		myPaint.setColor(Color.BLACK);
		myPaint.setStyle(Paint.Style.STROKE);

		//draw the boarder for this BoardSpace
		canvas.drawRect(startX, startY, startX + SPACE_SIZE, startY
				+ SPACE_SIZE, myPaint);

		if (drawEmblem) {
			//draws the mine in this BoardSpace
			myPaint.setColor(colors[spaceValue]);
			if (spaceValue == MINE) {
				myPaint.setStyle(Paint.Style.FILL);
				canvas.drawCircle(startX + (SPACE_SIZE / 2), startY
						+ (SPACE_SIZE / 2), SPACE_SIZE / 3, myPaint);
			} else {
				//draws the number of mines surrounding this BoardSpace
				myPaint.setTextSize((4 * SPACE_SIZE) / 5);
				canvas.drawText("" + spaceValue,
						startX + (5 * SPACE_SIZE / 16), startY
								+ (3 * SPACE_SIZE / 4), myPaint);
			}
		}
	}

	/**
	 * @param x  new top left x-coordinate for this BoardSpace
	 * @param y  new top left y-coordinate for this BoardSpace
	 */
	public void setCoordinate(int x, int y) {
		this.startX = x;
		this.startY = y;
	}

}
